<html>
 <head>
  <meta charset="utf-8"/>
  <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"/>
  <title>
   Rust语言入门、关键技术与实战经验  | 数螺 | NAUT IDEA
  </title>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" rel="stylesheet"/>
  <link href="http://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
  <style type="text/css">
   #xmain img {
                  max-width: 100%;
                  display: block;
                  margin-top: 10px;
                  margin-bottom: 10px;
                }

                #xmain p {
                    line-height:150%;
                    font-size: 16px;
                    margin-top: 20px;
                }

                #xmain h2 {
                    font-size: 24px;
                }

                #xmain h3 {
                    font-size: 20px;
                }

                #xmain h4 {
                    font-size: 18px;
                }


                .header {
	           background-color: #0099ff;
	           color: #ffffff;
	           margin-bottom: 20px;
	        }

	        .header p {
                  margin: 0px;
                  padding: 10px 0;
                  display: inline-block;  
                  vertical-align: middle;
                  font-size: 16px;
               }

               .header a {
                 color: white;
               }

              .header img {
                 height: 25px;
              }
  </style>
  <script src="http://cdn.bootcss.com/jquery/3.0.0/jquery.min.js">
  </script>
  <script src="http://nautstatic-10007657.file.myqcloud.com/static/css/readability.min.js" type="text/javascript">
  </script>
  <script type="text/javascript">
   $(document).ready(function() {
                 var loc = document.location;
                 var uri = {
                  spec: "http://dataunion.org/23184.html",
                  host: "http://dataunion.org",
                  prePath: "http://dataunion.org",
                  scheme: "http",
                  pathBase: "http://dataunion.org/"
                 };
    
                 var documentClone = document.cloneNode(true);
                 var article = new Readability(uri, documentClone).parse();
     
                 document.getElementById("xmain").innerHTML = article.content;
                });
  </script>
  <!-- 1466459850: Accept with keywords: (title(0.0):社区,关键技术,语言,数盟,实战经验,入门, topn(0.333333333333):大家,社区,语言,初始化,数盟,网络,编译,编译器,官网,定义,不怎么,例子,文章,类型,团队,数据,函数,性能,C++,问题,实战经验,错误,编程语言,代码,程序,开源,概念,线程,变量,分布式).-->
 </head>
 <body onload="">
  <div class="header">
   <div class="container">
    <div class="row">
     <div class="col-xs-6 col-sm-6 text-left">
      <a href="/databee">
       <img src="http://nautidea-10007657.cos.myqcloud.com/logo_white.png"/>
      </a>
      <a href="/databee">
       <p>
        数螺
       </p>
      </a>
     </div>
     <div class="hidden-xs col-sm-6 text-right">
      <p>
       致力于数据科学的推广和知识传播
      </p>
     </div>
    </div>
   </div>
  </div>
  <div class="container text-center">
   <h1>
    Rust语言入门、关键技术与实战经验
   </h1>
  </div>
  <div class="container" id="xmain">
   ﻿﻿
   <title>
    Rust语言入门、关键技术与实战经验 | 数盟社区
   </title>
   <!-- All in One SEO Pack 2.2.7.6.2 by Michael Torbert of Semper Fi Web Design[32,65] -->
   <!-- /all in one seo pack -->
   <!--
<div align="center">
<a href="http://strata.oreilly.com.cn/hadoop-big-data-cn?cmp=mp-data-confreg-home-stcn16_dataunion_pc" target="_blank"><img src="http://dataunion.org/wp-content/uploads/2016/05/stratabj.jpg"/ ></a>
</div>
-->
   <header id="header-web">
    <div class="header-main">
     <hgroup class="logo">
      <h1>
       <a href="http://dataunion.org/" rel="home" title="数盟社区">
        <img src="http://dataunion.org/wp-content/themes/yzipi/images/logo.png"/>
       </a>
      </h1>
     </hgroup>
     <!--logo-->
     <nav class="header-nav">
      <ul class="menu" id="menu-%e4%b8%bb%e8%8f%9c%e5%8d%95">
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-71" id="menu-item-71">
        <a href="http://dataunion.org/category/events" title="events">
         活动
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22457" id="menu-item-22457">
          <a href="http://dataunion.org/2016timeline">
           2016档期
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-22459" id="menu-item-22459">
          <a href="http://dataunion.org/category/parterc">
           合作会议
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor menu-item-has-children menu-item-20869" id="menu-item-20869">
        <a href="http://dataunion.org/category/tech" title="articles">
         文章
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20867" id="menu-item-20867">
          <a href="http://dataunion.org/category/tech/base" title="base">
           基础架构
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3302" id="menu-item-3302">
          <a href="http://dataunion.org/category/tech/ai" title="ai">
           人工智能
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3303" id="menu-item-3303">
          <a href="http://dataunion.org/category/tech/analysis" title="analysis">
           数据分析
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21920" id="menu-item-21920">
          <a href="http://dataunion.org/category/tech/dm">
           数据挖掘
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-3314" id="menu-item-3314">
          <a href="http://dataunion.org/category/tech/viz" title="viz">
           可视化
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-item-3305" id="menu-item-3305">
          <a href="http://dataunion.org/category/tech/devl" title="devl">
           编程语言
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-20876" id="menu-item-20876">
        <a href="http://dataunion.org/category/industry">
         行业
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-16328" id="menu-item-16328">
          <a href="http://dataunion.org/category/industry/case" title="case">
           行业应用
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-2112" id="menu-item-2112">
          <a href="http://dataunion.org/category/industry/demo" title="demo">
           Demo展示
          </a>
         </li>
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21562" id="menu-item-21562">
          <a href="http://dataunion.org/category/industry/news">
           行业资讯
          </a>
         </li>
        </ul>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-311" id="menu-item-311">
        <a href="http://dataunion.org/category/sources" title="sources">
         资源
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20870" id="menu-item-20870">
        <a href="http://dataunion.org/category/books" title="book">
         图书
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-21363" id="menu-item-21363">
        <a href="http://dataunion.org/category/training">
         课程
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-has-children menu-item-21853" id="menu-item-21853">
        <a href="http://dataunion.org/category/jobs">
         职位
        </a>
        <ul class="sub-menu">
         <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-22050" id="menu-item-22050">
          <a href="http://dataunion.org/category/career">
           职业规划
          </a>
         </li>
        </ul>
       </li>
      </ul>
     </nav>
     <!--header-nav-->
    </div>
   </header>
   <!--header-web-->
   <div id="main">
    <div id="soutab">
     <form action="http://dataunion.org/" class="search" method="get">
     </form>
    </div>
    <div id="container">
     <nav id="mbx">
      当前位置：
      <a href="http://dataunion.org">
       首页
      </a>
      &gt;
      <a href="http://dataunion.org/category/tech">
       文章
      </a>
      &gt;
      <a href="http://dataunion.org/category/tech/devl">
       编程语言
      </a>
      &gt;  正文
     </nav>
     <!--mbx-->
     <article class="content">
      <header align="centre" class="contenttitle">
       <div class="mscc">
        <h1 class="mscctitle">
         <a href="http://dataunion.org/23184.html">
          Rust语言入门、关键技术与实战经验
         </a>
        </h1>
        <address class="msccaddress ">
         <em>
          498 次阅读 -
         </em>
         <a href="http://dataunion.org/category/tech/devl" rel="category tag">
          编程语言
         </a>
        </address>
       </div>
      </header>
      <div class="content-text">
       <div>
        原文链接：
        <a href="http://it.dataguru.cn/article-9100-1.html">
         炼数成金
        </a>
       </div>
       <div>
        唐刘，PingCAP 首席架构师，现致力于下一代分布式数据库 TiDB、分布式存储 TiKV  的开发。开源爱好者，Go、Rust 等语言爱好者和实  践者。
       </div>
       <div>
       </div>
       <div>
        大家好，我是 PingCAP 的唐刘，今天很荣幸跟大家来分享一下 Rust 相关知识以及我们团队使用 Rust 的实战经验。
       </div>
       <div>
       </div>
       <div>
        为什么选择Rust
       </div>
       <div>
        首先来说说最近 Go 社区讨论比较多的事情，Dropbox 将底层的类 S3 服务改用 Rust 来重写了，一下子让 Rust 增加了很多知名度，谁叫 Dropbox 这种公司通常都是技术架构上面的风向标。大家普通关注的一个问题：
       </div>
       <div>
       </div>
       <div>
        为什么 Dropbox 不用 Go，反而用一门学习曲线比较陡峭的 Rust 来进行开发？
       </div>
       <div>
       </div>
       <div>
        其实这个问题也同样适用于我们，一个自认为 Go 经验非常丰富的团队，为什么不用 Go 反而要选择 Rust？
       </div>
       <div>
       </div>
       <div>
        介绍一下我们在做的事情。我们团队从事的是下一代分布式数据库的开发，也就是俗称的 NewSQL，整个理论基础基于 Google 的 F1 以及 Spanner，所以自然我们的 NewSQL 也是分成了两块，一个是无状态的 SQL 层，也就是现阶段已经开源出来的 TiDB（http://dwz.cn/2XZkSm），另一个就是分布式 KV 层，我们叫做 TiKV，预计会在4月份开源。
       </div>
       <div>
        <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154709k00kf7dcpzarf6p5.png" target="_blank">
         <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154709k00kf7dcpzarf6p5.png"/>
        </a>
       </div>
       <div>
        TiDB 是使用 Go 编写的，熟悉 Go 的同学都应该知道，用 Go 来写分布式应用那是非常的快捷方便的，而且我们团队的成员都有非常深厚的 Go 编程经验，但是在决定做 TiKV 的时候，我们没有使用 Go，或者使用 C++，Java 这些更流行的静态语言，反而是选择了一门我们自身完全不熟悉的语言 Rust，Why？
       </div>
       <div>
       </div>
       <div>
        先来说说使用 Go 会遇到的问题：
       </div>
       <div>
       </div>
       <div>
        GC，虽然 1.6 之后 Go 的 GC 已经改善的很好了，而且我们觉得以后会越来越好，但是对于一个对性能要求非常高的分布式应用，我们倾向选择一门没有 GC 的语言，这样在内存上面更加可控。
       </div>
       <div>
        Cgo，TiKV 使用 RocksDB 作为其底层存储 engine，如果用 Go，我们需要使用 Cgo 来进行 RocksDB的调用，而 Cgo 对性能还是有比较大的损耗的。
       </div>
       <div>
       </div>
       <div>
        再来说说不选择 C++ 或者 Java，C++ 主要是大规模开发对整个团队要求非常高，而我们自己也觉得用 C++ 不可能 hold 住在短时间内做出产品，所以自然放弃。而 Java，我们团队没几个人精通 Java，也直接放弃了。
       </div>
       <div>
       </div>
       <div>
        所以，我们最终将目光落到了 Rust 上面，主要在于 Rust 有几个很 cool 的 feature，就是 type safety，memory safety 以及 thread safety，这个后续详细说明。
       </div>
       <div>
       </div>
       <div>
        Rust 的基础入门
       </div>
       <div>
        在 Rust 的官网上面，我们可以看到 Rust 的介绍，它是一门系统编程语言，性能好，同时在编译阶段就能帮你检测出内存，多线程数据访问等问题，保证程序安全健壮。
       </div>
       <div>
       </div>
       <div>
        也就是说，使用 Rust 写程序，如果能通过编译，你就不用担心类似 C++ 里面很多 memory leak，segment faut，data race 的问题了，但这一切都是有代价的。Rust 上手非常不容易，难度可以跟 C++ 媲美，如果是 Go，没准学习一个星期都能开始给项目贡献代码，但换成 Rust，可能一个月都还在跟编译器作斗争，研究为啥自己的代码编译不过。
       </div>
       <div>
       </div>
       <div>
        因为我不清楚大家有多少人接触过 Rust，所以这里列出来一些例子，让大家对 Rust 的语法有一个基本了解。
       </div>
       <div>
       </div>
       <div>
        首先就是最通用的 Hello world：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154709l173716u13jajzj0.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154709l173716u13jajzj0.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        fn 是 Rust 的关键字，用来定义函数，函数名字是 main, println! 是一个 macro，在 rust style 里面，macro 都是在末尾使用“!”来表示的。
       </div>
       <div>
       </div>
       <div>
        我们接下来定义几个变量，下面就开始显示出 rust 跟其他语言的不一样的地方了：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154709pzntqzztn7n7mn2j.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154709pzntqzztn7n7mn2j.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面我们声明了一个 u32 类型的变量，但是没有初始化，然后打印它的值，在一些语言里面，譬如 Go，会打印出 0，但是在 Rust 里面，这没法编译通过，编译器会提示：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154709sd6gu4zd9gsdus95.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154709sd6gu4zd9gsdus95.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面的错误告诉我们使用了一个没有初始化的变量，我们先来初始化一下，变成这样：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154709kwwigididvvst8qw.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154709kwwigididvvst8qw.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面我们首先定义了一个初始值为 0 的变量，然后改成 10 打印，编译，发现如下错误：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154709wlhzwfwkphn4iwiv.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154709wlhzwfwkphn4iwiv.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        这次编译器告诉我们对一个 immutable 的变量进行了更改。在 Rust 里面，变量是分为 immutable 和 mutable 的，我们必须显示地定义这个变量到底能不能改动。我们使用 mut 关键字来告诉 Rust 这个变量是 mutable 的，如下：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154710zlwlopqzqtt2tths.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154710zlwlopqzqtt2tths.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        这下就能正常编译了。
       </div>
       <div>
       </div>
       <div>
        通过上面一些简单的例子，大家应该对 Rust 有了一个初步的印象，更加详细的了解可以去参考官网。
       </div>
       <div>
       </div>
       <div>
        让 Rust 开发变 easy 的关键技术点
       </div>
       <div>
        前面在为什么选择 Rust 里面，我提到了因为 Rust 有几个很 cool 的特性，能让我们写出不容易出错的并发程序。而且我认为，只要理解掌握了这个关键点，用 Rust 进行程序开发就很 easy了。
       </div>
       <div>
       </div>
       <div>
        Type safety
       </div>
       <div>
        Rust 是一门严格要求类型安全的语言，在 C/C++ 的世界里面，我们可以无拘无束的进行类型转换，譬如：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154710dhkkbtkwnhetwbbq.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154710dhkkbtkwnhetwbbq.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        这种在 C/C++  里面很常见的处理方式，在 Rust 里面是不被允许的，譬如：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154710p0ztwtrlltkkgxjk.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154710p0ztwtrlltkkgxjk.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        我们会得到如下编译错误：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/155107zpubwpkbpskxtgsb.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/155107zpubwpkbpskxtgsb.png"/>
         </a>
        </p>
       </div>
       <div>
        如果强制做这种内存转换，我们可以使用 unsafe，显示的告诉 Rust 这么做是不安全的，但是你别管了：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154710ty4fb3dzidy7fw37.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154710ty4fb3dzidy7fw37.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        通常情况下面，Rust 是不允许写上面这样的代码的，所以它将 unsafe 的选择权显示的交给了程序员，而我们通过 unsafe 也能清晰的知道哪里是不安全的代码，需要注意的。
       </div>
       <div>
       </div>
       <div>
        Memory safety
       </div>
       <div>
        下面进入 Rust 最令人抓狂的一个关键点了。Rust 是能够保证程序的 memory  safety 的，那么是如何保证的呢？首先我们需要了解的是 Rust 里面 ownership 以及 move 的概念。
       </div>
       <div>
       </div>
       <div>
        Ownership + move
       </div>
       <div>
        在Rust里面，任何资源只可能有一个 ownership，譬如一个最简单的例子：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154710dq4mtnshq4ziyq6i.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154710dq4mtnshq4ziyq6i.png"/>
         </a>
        </p>
       </div>
       <div>
        这里我们使用 let 将一个 vector 给绑定到 a 这个变量上面了，我们就可以认为 a 现在是这个 vector 的 ownership。然后对于这个 vector 的 resouce，同一个时间只允许一个 ownership。我们来看下面这个代码：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154710temc6iv6zsdptt6j.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154710temc6iv6zsdptt6j.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        在上面的例子中，我们将 a 赋值给了 b，同时继续打印 a[0] 的值，这个在大多数语言都没有任何问题的操作，在 Rust 里面，是会报错的，如下：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154711w7n5y4yiquyrquqy.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154711w7n5y4yiquyrquqy.png"/>
         </a>
        </p>
       </div>
       <div>
        为什么呢？在打印 a[0] 之前，我们进行了 let b = a 这样的操作，这个操作，在 Rust 里面叫做 move，含义就是把 a 对 vector 的 ownership 移交给了 b，a 放弃了对 vector 的 ownership。因为 a 已经对这个 vector 没有 ownership 了，自然就不能访问相关的数据了。
       </div>
       <div>
       </div>
       <div>
        ownership 和 move 的概念应该算是学习 Rust 第一个坑，我们也很容易写出如下代码：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154711g11iu1u3wfqsc9wc.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154711g11iu1u3wfqsc9wc.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        这个代码照样是编译不过的，因为 do_vec 这个函数，a 已经将对 vector 的 ownership 给 move 了。
       </div>
       <div>
       </div>
       <div>
        所以通常我们只要看到 let b = a 这样的代码，就表明 a move 掉了 ownership 了，但有一个例外，如果a的类型实现了copy trait，let b =a 就不是move，而是 copy 了，下面的代码是能正常编译的：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154711c5yirny96e1ee8s5.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154711c5yirny96e1ee8s5.png"/>
         </a>
        </p>
       </div>
       <div>
        上面的代码里面，let b = a，a 并没有 move，而是将自己的数据 copy 了一份给 b 使用。通常基本的数据类型都是实现了 copy trait，当然我们也可以将我们自定义的类型实现 copy，只是就需要权衡下 copy 的性能问题了。
       </div>
       <div>
       </div>
       <div>
        Borrow
       </div>
       <div>
        前面我们举了一个 do_vec 的例子，如果真的需要在调用这个函数之后继续使用这个 vector，怎么办呢？
       </div>
       <div>
       </div>
       <div>
        这里我们就开始接触到了第二个坑，borrow。上面说了，move 是我给你了 ownership，而 borrow 则是我借给你这个 resource 的使用权，到时候还要还给我：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154711iu9pddpscoddxsiu.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154711iu9pddpscoddxsiu.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面的例子中，我们在参数里面使用了 &amp; 来表示 borrow，do_vec 这个函数只是借用了 a，然后函数结束之后，还了回来，这样后续我们就能继续使用 a 了。
       </div>
       <div>
       </div>
       <div>
        既然 borrow，当然就能用了，于是我们就可能写这样的代码：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154711bozvgudw8j7u7ud7.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154711bozvgudw8j7u7ud7.png"/>
         </a>
        </p>
       </div>
       <div>
        然后 Rust 又华丽丽的报错了，输出:
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154711rmiyi6vvi1d1yykd.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154711rmiyi6vvi1d1yykd.png"/>
         </a>
        </p>
       </div>
       <div>
        因为我们的 borrow 只是 immutable 的 borrow，并不能改数据。在前面我们也提到过，如果要对一个变量进行修改，必须显示的用 mut 进行声明，borrow 也是一样，如果要对一个 borrow 的东西显示修改，必须使用 mutable borrow，也就是这样：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154712glhpaeleo644epko.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154712glhpaeleo644epko.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        borrow 还有 scope 的概念，有时候我们写这样的代码：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154712mtk2x68vx1y25oo8.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154712mtk2x68vx1y25oo8.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        发现编译器又报错了，输出：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154712zcit31usn03qkaib.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154712zcit31usn03qkaib.png"/>
         </a>
        </p>
       </div>
       <div>
        因为我们之前用 y 来对 x 进行了mutable 的 borrow，但是还没还回去，所以后面 immutable的 borrow 就不允许。这个我们可以通过 scope 来显示的控制 mutable 的生存周期：
       </div>
       <div>
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154712ztrkf44kqktf6yqv.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154712ztrkf44kqktf6yqv.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        这样在 printIn! 进行 immutable 的 borrow 的时候，y 这个mutable 的 borrow 已经还回来了。
       </div>
       <div>
       </div>
       <div>
        一个变量，可以同时进行多个 immutable 的 borrow，但只允许一个 mutable 的 borrow，这个其实跟 read-write lock 很相似，同时允许多个读锁，但一次只允许一个写锁。
       </div>
       <div>
       </div>
       <div>
        Lifetime
       </div>
       <div>
        在 C++ 里面，相信大家对野指针都印象深刻，有时候，我们会引用了一个已经被 delete 的对象，然后再次使用的时候就 panic 了。在 Rust 里面，是通过 lifetime 来解决这个问题的，不过引入了 lifetime 之后，代码看起来更丑了。一个简单的例子：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154712lx04uc1tuchx448n.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154712lx04uc1tuchx448n.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        我们定义了一个 struct，里面的 field b 是对外面一个 u32 变量的引用，而这个引用的 lifetime是 ’a。使用 lifetime 能保证b 引用的 u32 数据的生存周期一定是大于 A 的。
       </div>
       <div>
       </div>
       <div>
        但是在上面的例子中，我们在一个 scope 里面，让 b 引用了 c，但是 c 在 scope 结束之后就没了，这时候 b 就是一个无效的引用了，所以 Rust 会编译报错：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154713uvu7o2tvnnow7wu6.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154713uvu7o2tvnnow7wu6.png"/>
         </a>
        </p>
       </div>
       <div>
        Thread safety
       </div>
       <div>
        前面我们提到，Rust 使用 move，borrow 以及 lifetime 这些机制来保证 memory safety，虽然这几个概念不怎么好理解，而且很容易大家写代码的时候就会陷入与编译器的斗争，但是我个人觉得只要理解了这些概念，写 Rust 就不是问题了。
       </div>
       <div>
       </div>
       <div>
        好了，说完了 memory safety，我们马上进入 thread safety了。大家都知道，多线程的程序很难写，有且稍微不注意，就会出现 data race 等情况，导致数据错误，而且偏偏这样的 bug 还能难查出来。
       </div>
       <div>
       </div>
       <div>
        譬如在 Go 里面，我们可以这样：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154713bik9x2puerc9iocx.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154713bik9x2puerc9iocx.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面的例子很极端，大家应该也不会这面写代码，但实际中，我们仍然可能会面临 data race 的问题。虽然 Go 可以通过 –race 打开 data race 的检查，可通常只会用于 test，而不会在线上使用。
       </div>
       <div>
       </div>
       <div>
        而 Rust 则是在源头上面完全让大家没法写出 data race 的代码。首先我们先来了解 Rust 两个针对并发的 trait，Send和 Sync：
       </div>
       <div>
       </div>
       <div>
        Send
       </div>
       <div>
        当一个类型实现了 Send，我们就可以认为这个类型可以安全的从一个线程 move 给另一个线程去使用。
       </div>
       <div>
        Sync
       </div>
       <div>
        当一个类型实现了 Sync，我们就可以认为这个类型可以在多线程里面通过 shared reference（也就是 Arc）安全的使用。
       </div>
       <div>
       </div>
       <div>
        上面的概念看起来比较困惑，简单一点就是如果一个类型实现了Send + Sync，那么这个就能在多线程下面安全的使用。
       </div>
       <div>
       </div>
       <div>
        先来看一个简单的例子：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154713h4xf46441mol16om.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154713h4xf46441mol16om.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面就是一个典型的多线程 data race 的问题了，Rust 是编译不过的，报错:
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154713r66d06d8llg860e6.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154713r66d06d8llg860e6.png"/>
         </a>
        </p>
       </div>
       <div>
        前面说了，我们可以通过 Arc 来保证自己的类型在多线程下面安全使用，我们加上 Arc。
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154713lf8nnh1tx1s1hua8.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154713lf8nnh1tx1s1hua8.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        现在我们的 vector 能多线程访问了，但是仍然出错：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154713qc6ud6yt742s4tdr.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154713qc6ud6yt742s4tdr.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        因为我们不光是要多线程 read，而且还需要多线程去 write，自然 Rust 不允许，所以我们需要显示的进行加锁保护，如下：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154714kj1f4cw44ix0xi40.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154714kj1f4cw44ix0xi40.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        所以，如果我们要对一个数据进行安全的多线程使用，最通用的做法就是使用 Arc&lt;Mutex&lt;T&gt;&gt; 或者 Arc&lt;RwLock&lt;T&gt;&gt;进行封装使用。
       </div>
       <div>
       </div>
       <div>
        当然，除了 Arc + Lock 之外，Rust 还提供了 channel 机制方便进行线程之间的数据通讯，channel 类似于 Go 的 channel，一端 send，一端 recv，这里就不详细说明了。
       </div>
       <div>
       </div>
       <div>
        这里在提一点，因为在 Rust 里面，对于多线程使用的数据，我们必须明确的进行 lock 保护，这个编程风格直接带到了后来我们写 Go 。在 Go 里面，我以前写 lock，通常会这样：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154716iinrrnbwnah58zvy.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154716iinrrnbwnah58zvy.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        使用一个 mutex 变量 m 来对数据 v1，v2 进行多线程保护，但这种写法其实很容易就容易忘记这个 lock 到底要保护哪些数据。自从受 Rust 影响了之后，我就喜欢写成这样了：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154718ge8r8epum77mmmaw.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154718ge8r8epum77mmmaw.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        上面就是显示的将 lock 以及需要保护的数据放到一个 struct 里面，大家一看代码就知道这个 lock 要保护哪些数据了。
       </div>
       <div>
       </div>
       <div>
        Rust 开发实战经验
       </div>
       <div>
        前面说了是 Rust 的一些基本 feature，这里开始说下我们项目中用 Rust 的相关经验。
       </div>
       <div>
       </div>
       <div>
        Cargo
       </div>
       <div>
        如果要用 Rust进行项目开发，首先就需要了解的就是 Cargo，Cargo 是 Rust 一个构建以及包管理工具，现在应该已经成了 Rust 开发项目的规范了。Cargo 的使用还是很简单的，大家可以直接去看浏览官网 （https://crates.io/）。
       </div>
       <div>
       </div>
       <div>
        quick_error!
       </div>
       <div>
        最开始，我们在写 C 程序的时候，通过定义不同的 int 返回值来表示一个函数是不是有 error。然后到了 C++，我们就可以通过 expection 来处理 error 了。不过到底采用哪种标准，都是没有定论的。
       </div>
       <div>
       </div>
       <div>
        到了 Go，直接约定了函数最后一个返回参数是 error，官方还有一篇 blog 来介绍了 Go 的error handling （http://blog.golang.org/error-handling-and-go）。
       </div>
       <div>
       </div>
       <div>
        在 Rust 里面，error 也有相应的处理规范，就是 Result，Result 是一个 enum，定义是这样的:
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154718zg31c9y2i33qy39t.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154718zg31c9y2i33qy39t.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        也就是说，我们的函数都可以返回 Result，外面去判断，如果是 Ok，那么就是正确的处理，如果是 Err 则是错误了。
       </div>
       <div>
       </div>
       <div>
        这里有篇 error handling 的详细说明 （https://doc.rust-lang.org/book/error-handling.html）。
       </div>
       <div>
       </div>
       <div>
        通常大家都会按照上面的规范来处理 error，也就是定义自己的 error，实现其他 error 转成自己 error 的 from 函数，然后在使用 try! 在代码里面简化 error 的处理。
       </div>
       <div>
       </div>
       <div>
        但是很快我们就发现了一个很严重的问题，定义自己的 error，以及将其他 error 转成我们对应的 error 是一件非常冗余复杂的事情，所以我们使用 quick_error!（http://dwz.cn/2XZpNo）来简化整个流程。
       </div>
       <div>
       </div>
       <div>
        Clippy
       </div>
       <div>
        当我第一次写 Go 代码的时候，我对 Go 的 fmt 印象特别深刻，以后再也不用担心编码风格的争论了，Rust 也有相关的 rust fmt，但是更令我惊奇的是 Rust 的 Clippy 这个工具。Clippy 已经不是纠结于编码风格了，而是直接告诉你代码要这么写，那么写不对。
       </div>
       <div>
       </div>
       <div>
        一个很简单的例子：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154718q4txigz153rv59v0.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154718q4txigz153rv59v0.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        这个代码是能编译通过的，但是如果我们打开了 Clippy 的支持，直接会提示：
       </div>
       <div>
        <p>
         <a href="http://attach.dataguru.cn/attachments/portal/201603/25/154718o9ug6i2cvci6ieuz.png" target="_blank">
          <img src="http://attach.dataguru.cn/attachments/portal/201603/25/154718o9ug6i2cvci6ieuz.png"/>
         </a>
        </p>
       </div>
       <div>
       </div>
       <div>
        也就是告诉你，别用 to_string，用 to_owned。
       </div>
       <div>
       </div>
       <div>
        我们都知道，要开发一个高性能的网络服务，通常的选择就是 epoll 这种基于事件触发的网络模型，在 Rust，现阶段成熟的库就是 MIO。MIO是一个异步 IO 库，对不同的操作系统提供了统一抽象支持，譬如 Linux 下面就是 epoll，UNIX 下面就是 kqueue，Windows 下是 IOCP。不过 MIO 为了统一扩平台，在一些实现上面做了妥协。
       </div>
       <div>
       </div>
       <div>
        MIO
       </div>
       <div>
        譬如在 Linux 下面，系统直接提供了 event fd 的支持，但 MIO 为了兼容 UNIX，使用了传统的 pipe 而不是 event fd 来进行 event loop 的 awake 处理。
       </div>
       <div>
       </div>
       <div>
        这里在单独说下 MIO 提供的另一种线程通讯 channel 机制，虽然我们可以用 Rust 自己的 thread channel 来进行线程通讯，但如果引入 MIO，我更喜欢用 MIO 自己的 channel，主要原因是采用的 lock free queue，性能更好，但有 queue size 限制问题，发送太频繁但接受端没处理过来，就会造成发送失败的问题了。
       </div>
       <div>
       </div>
       <div>
        Rust 语言的美中不足
       </div>
       <div>
        我们团队已经使用 Rust进行了几个月的开发，当然也遇到了一些很不爽的地方。
       </div>
       <div>
       </div>
       <div>
        首先就是库的不完善，相比于 Go，Rust 的库真的太不完备了。我觉得现阶段 Rust 仍然没有大规模的应用，lib 不完备占了很大一个原因。
       </div>
       <div>
       </div>
       <div>
        TiKV 是一个服务器程序，自然就会涉及到网络编程，官方现阶段的 net mod 里面，只有 block socket 的支持，这个完全没法用来开发高性能网络程序的。幸好有 MIO，但光有 MIO 是远远不够，在 Go 里面，我们很方便的使用 gRPC 来进行 RPC 的编写，但是在 Rust 里面，我觉得还得在等很长一段时间，看能不能有开源的实现。
       </div>
       <div>
       </div>
       <div>
        再来就是在 Mac OS X 下面，panic 出来的堆栈完全没法看，没有 file 和 line number 的信息，根本没法方便的查 bug。
       </div>
       <div>
       </div>
       <div>
        当然，毕竟 Rust 是一门比较新的语言，还在不断的完善发展，我们还是很有信心它能越来越好的。
       </div>
       <div>
       </div>
       <div>
        Q &amp; A
       </div>
       <div>
        1. Go 的 Cgo 在效率上面与 Rust FFI 有啥区别？
       </div>
       <div>
        唐刘：我自己写过一个简单的测试，就是都循环调用 Snappy 的 MaxCompressedLength 这个函数 10000 次，发现 Rust 的 FFI 比 Go 的 Cgo 要快上一个数量级，虽然这么测试不怎么精确，但至少证明了 Rust 的 FFI 性能更好。
       </div>
       <div>
       </div>
       <div>
        2. 在官方的介绍中，Rust 的首选平台是 Windows, 那是否可以生成 dll. 你们的 IDE 用的是什么？
       </div>
       <div>
        唐刘：我没用过 Windows，所以也不知道怎么生成 dll，开发 Rust 的 ide 也就是常用的那几个，譬如 Vim， Emacs， Sublime 这些，反正都有 Rust 的插件支持。
       </div>
       <div>
       </div>
       <div>
        3. Rust 调用 C 的库方便吗？
       </div>
       <div>
        唐刘：Rust 通过 FFI 调用 C，很方便的，这里有相关文档 （https://doc.rust-lang.org/book/ffi.html），但毕竟这涉及到跨语言，代码写起来就不怎么好看了。而且 FFI 需要 unsafe保护，所以通常我们会在外面在 wrap 一层 Rust 的函数。
       </div>
       <div>
       </div>
       <div>
        4. Rust 性能指标如何？
       </div>
       <div>
        唐刘：Rust 性能这个不怎么好衡量，因为我们只是在一些特定的环境下面做过跟 Go 的对比，譬如 Cgo vs FFI 的测试，这方面性能是比 Go 要好的。另外，Rust 是一门静态语言，没有 GC，所以我觉得他的性能不会是问题，不然 Dropbox 也不可能将类 S3 的应用用 Rust 写了。
       </div>
       <div>
       </div>
       <div>
        5. Rust 周边生态如何? 如跟常用的 DBSQL/MQ 等第三方系统的 binding？
       </div>
       <div>
        唐刘：Rust 的生态只能呵呵来形容了，跟 Go，Java 这些的没法比。虽然有常用的 MySQL 等的 binding，但我没用过。主要原因在于官方的网络 IO 是同步的，所以必须借助多线程来进行这些处理，而用 MIO 这种异步模式，大家也知道写出来的代码逻辑切割很厉害。所以通常我们也不会拿 Rust 来做这些复杂的业务系统开发，感觉还是 Go 更合适。
       </div>
      </div>
      <div>
       <strong>
        注：转载文章均来自于公开网络，仅供学习使用，不会用于任何商业用途，如果侵犯到原作者的权益，请您与我们联系删除或者授权事宜，联系邮箱：contact@dataunion.org。转载数盟网站文章请注明原文章作者，否则产生的任何版权纠纷与数盟无关。
       </strong>
      </div>
      <!--content_text-->
      <div class="fenxian">
       <!-- JiaThis Button BEGIN -->
       <div class="jiathis_style_32x32">
        <p class="jiathis_button_weixin">
        </p>
        <p class="jiathis_button_tsina">
        </p>
        <p class="jiathis_button_qzone">
        </p>
        <p class="jiathis_button_cqq">
        </p>
        <p class="jiathis_button_tumblr">
        </p>
        <a class="jiathis jiathis_txt jtico jtico_jiathis" href="http://www.jiathis.com/share" target="_blank">
        </a>
        <p class="jiathis_counter_style">
        </p>
       </div>
       <!-- JiaThis Button END -->
      </div>
     </article>
     <!--content-->
     <!--相关文章-->
     <div class="xianguan">
      <div class="xianguantitle">
       相关文章！
      </div>
      <ul class="pic">
       <li>
        <a href="http://dataunion.org/24678.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/20140917125452915416-216x200.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/24678.html" rel="bookmark" title="python3中的正则模块">
         python3中的正则模块
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/24675.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/t015b337bd75d9ef893-161x200.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/24675.html" rel="bookmark" title="注释是恶魔，请不要再写一行注释">
         注释是恶魔，请不要再写一行注释
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/24660.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/u16130037972892789947fm21gp0-300x157.jpg"/>
        </a>
        <a class="link" href="http://dataunion.org/24660.html" rel="bookmark" title="如何从Github上轻松安装R包">
         如何从Github上轻松安装R包
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/24654.html">
         <img src="http://dataunion.org/wp-content/uploads/2016/06/df53fac99fc53ba5a90666abcca25e6d_b-267x200.png"/>
        </a>
        <a class="link" href="http://dataunion.org/24654.html" rel="bookmark" title="简单形象又有趣地说说强大的神经网络">
         简单形象又有趣地说说强大的神经网络
        </a>
       </li>
      </ul>
     </div>
     <!--相关文章-->
     <div class="comment" id="comments">
      <!-- You can start editing here. -->
      <!-- If comments are open, but there are no comments. -->
      <div class="title">
       期待你一针见血的评论，Come on！
      </div>
      <div id="respond">
       <p>
        不用想啦，马上
        <a href="http://dataunion.org/wp-login.php?redirect_to=http%3A%2F%2Fdataunion.org%2F23184.html">
         "登录"
        </a>
        发表自已的想法.
       </p>
      </div>
     </div>
     <!-- .nav-single -->
    </div>
    <!--Container End-->
    <aside id="sitebar">
     <div class="sitebar_list2">
      <div class="wptag">
       <span class="tagtitle">
        热门标签+
       </span>
       <div class="tagg">
        <ul class="menu" id="menu-%e5%8f%8b%e6%83%85%e9%93%be%e6%8e%a5">
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-1605" id="menu-item-1605">
          <a href="http://taidizh.com/">
           泰迪智慧
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-20884" id="menu-item-20884">
          <a href="http://www.transwarp.cn/">
           星环科技
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-3538" id="menu-item-3538">
          <a href="http://datall.org/">
           珈和遥感
          </a>
         </li>
         <li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-20888" id="menu-item-20888">
          <a href="http://www.chinahadoop.cn/">
           小象学院
          </a>
         </li>
        </ul>
       </div>
      </div>
     </div>
     <div class="sitebar_list">
      <div class="textwidget">
       <div align="center">
        <a href="http://study.163.com/course/courseMain.htm?courseId=991022" target="_blank">
         <img src="http://dataunion.org/wp-content/uploads/2016/03/dv.jpg"/>
        </a>
       </div>
      </div>
     </div>
     <div class="sitebar_list">
      <h4 class="sitebar_title">
       文章分类
      </h4>
      <div class="tagcloud">
       <a class="tag-link-44" href="http://dataunion.org/category/industry/demo" style="font-size: 10.204724409449pt;" title="4个话题">
        Demo展示
       </a>
       <a class="tag-link-31" href="http://dataunion.org/category/experts" style="font-size: 15.826771653543pt;" title="52个话题">
        专家团队
       </a>
       <a class="tag-link-870" href="http://dataunion.org/category/tech/ai" style="font-size: 19.795275590551pt;" title="273个话题">
        人工智能
       </a>
       <a class="tag-link-488" href="http://dataunion.org/category/%e5%8a%a0%e5%85%a5%e6%95%b0%e7%9b%9f" style="font-size: 8pt;" title="1个话题">
        加入数盟
       </a>
       <a class="tag-link-869" href="http://dataunion.org/category/tech/viz" style="font-size: 17.204724409449pt;" title="93个话题">
        可视化
       </a>
       <a class="tag-link-30" href="http://dataunion.org/category/partners" style="font-size: 10.645669291339pt;" title="5个话题">
        合作伙伴
       </a>
       <a class="tag-link-889" href="http://dataunion.org/category/parterc" style="font-size: 11.582677165354pt;" title="8个话题">
        合作会议
       </a>
       <a class="tag-link-104" href="http://dataunion.org/category/books" style="font-size: 12.96062992126pt;" title="15个话题">
        图书
       </a>
       <a class="tag-link-220" href="http://dataunion.org/category/tech/base" style="font-size: 19.850393700787pt;" title="281个话题">
        基础架构
       </a>
       <a class="tag-link-219" href="http://dataunion.org/category/tech/analysis" style="font-size: 19.409448818898pt;" title="232个话题">
        数据分析
       </a>
       <a class="tag-link-887" href="http://dataunion.org/category/tech/dm" style="font-size: 13.291338582677pt;" title="17个话题">
        数据挖掘
       </a>
       <a class="tag-link-34" href="http://dataunion.org/category/tech" style="font-size: 20.732283464567pt;" title="404个话题">
        文章
       </a>
       <a class="tag-link-1" href="http://dataunion.org/category/uncategorized" style="font-size: 22pt;" title="693个话题">
        未分类
       </a>
       <a class="tag-link-4" href="http://dataunion.org/category/events" style="font-size: 14.503937007874pt;" title="29个话题">
        活动
       </a>
       <a class="tag-link-890" href="http://dataunion.org/category/tech/%e6%b7%b1%e5%ba%a6%e5%ad%a6%e4%b9%a0" style="font-size: 10.204724409449pt;" title="4个话题">
        深度学习
       </a>
       <a class="tag-link-221" href="http://dataunion.org/category/tech/devl" style="font-size: 18.968503937008pt;" title="193个话题">
        编程语言
       </a>
       <a class="tag-link-888" href="http://dataunion.org/category/career" style="font-size: 15.661417322835pt;" title="48个话题">
        职业规划
       </a>
       <a class="tag-link-5" href="http://dataunion.org/category/jobs" style="font-size: 14.11811023622pt;" title="25个话题">
        职位
       </a>
       <a class="tag-link-871" href="http://dataunion.org/category/industry" style="font-size: 15.716535433071pt;" title="49个话题">
        行业
       </a>
       <a class="tag-link-613" href="http://dataunion.org/category/industry/case" style="font-size: 16.984251968504pt;" title="84个话题">
        行业应用
       </a>
       <a class="tag-link-885" href="http://dataunion.org/category/industry/news" style="font-size: 17.425196850394pt;" title="102个话题">
        行业资讯
       </a>
       <a class="tag-link-10" href="http://dataunion.org/category/training" style="font-size: 14.228346456693pt;" title="26个话题">
        课程
       </a>
       <a class="tag-link-16" href="http://dataunion.org/category/sources" style="font-size: 15.661417322835pt;" title="48个话题">
        资源
       </a>
      </div>
     </div>
     <div class="sitebar_list">
      <h4 class="sitebar_title">
       功能
      </h4>
      <ul>
       <li>
        <a href="http://dataunion.org/wp-login.php?action=register">
         注册
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/wp-login.php">
         登录
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/feed">
         文章
         <abbr title="Really Simple Syndication">
          RSS
         </abbr>
        </a>
       </li>
       <li>
        <a href="http://dataunion.org/comments/feed">
         评论
         <abbr title="Really Simple Syndication">
          RSS
         </abbr>
        </a>
       </li>
       <li>
        <a href="https://cn.wordpress.org/" title="基于WordPress，一个优美、先进的个人信息发布平台。">
         WordPress.org
        </a>
       </li>
      </ul>
     </div>
    </aside>
    <div class="clear">
    </div>
   </div>
   <!--main-->
   ﻿
   <footer id="dibu">
    <div class="about">
     <div class="right">
      <ul class="menu" id="menu-%e5%ba%95%e9%83%a8%e8%8f%9c%e5%8d%95">
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-18024" id="menu-item-18024">
        <a href="http://dataunion.org/category/partners">
         合作伙伴
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20881" id="menu-item-20881">
        <a href="http://dataunion.org/contribute">
         文章投稿
        </a>
       </li>
       <li class="menu-item menu-item-type-taxonomy menu-item-object-category menu-item-20872" id="menu-item-20872">
        <a href="http://dataunion.org/category/%e5%8a%a0%e5%85%a5%e6%95%b0%e7%9b%9f">
         加入数盟
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-22441" id="menu-item-22441">
        <a href="http://dataunion.org/f-links">
         友情链接
        </a>
       </li>
       <li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-20874" id="menu-item-20874">
        <a href="http://dataunion.org/aboutus">
         关于数盟
        </a>
       </li>
      </ul>
      <p class="banquan">
       数盟社区        ，
        做最棒的数据科学社区
      </p>
     </div>
     <div class="left">
      <ul class="bottomlist">
       <li>
        <a href="http://weibo.com/DataScientistUnion  " target="_blank" 　title="">
         <img src="http://dataunion.org/wp-content/themes/yzipi/images/weibo.png"/>
        </a>
       </li>
       <li>
        <a class="cd-popup-trigger" href="http://dataunion.org/23184.html#0">
         <img src="http://dataunion.org/wp-content/themes/yzipi/images/weixin.png"/>
        </a>
       </li>
      </ul>
      <div class="cd-popup">
       <div class="cd-popup-container">
        <h1>
         扫描二维码,加微信公众号
        </h1>
        <img src="http://dataunion.org/wp-content/themes/yzipi/images/2014-12-06-1515289049.png"/>
        <a class="cd-popup-close" href="http://dataunion.org/23184.html">
        </a>
       </div>
       <!-- cd-popup-container -->
      </div>
      <!-- cd-popup -->
     </div>
    </div>
    <!--about-->
    <div class="bottom">
     <a href="http://dataunion.org/">
      数盟社区
     </a>
     <a href="http://www.miitbeian.gov.cn/" rel="external nofollow" target="_blank">
      京ICP备14026740号
     </a>
     联系我们：
     <a href="mailto:contact@dataunion.org" target="_blank">
      contact@dataunion.org
     </a>
     <div class="tongji">
     </div>
     <!--bottom-->
     <div class="scroll" id="scroll" style="display:none;">
      ︿
     </div>
    </div>
   </footer>
   <!--dibu-->
  </div>
 </body>
</html>